package com.vdimitr.happycube.puzzle.matrix;

import com.vdimitr.happycube.puzzle.piece.PuzzlePiece;
import com.vdimitr.happycube.puzzle.piece.PuzzlePieceFlip;
import com.vdimitr.happycube.puzzle.piece.PuzzlePieceRotation;

/**
 * This class contains methods for adjusting the matrix of a puzzle piece based
 * on its flip {@link PuzzlePieceFlip }and rotation {@link PuzzlePieceRotation}.
 * 
 * @see PuzzlePieceFlip
 * @see PuzzlePieceRotation
 * 
 * @author vasileios.dimitriadis
 * 
 */
public class PuzzlePieceMatrixTransformer {

	/**
	 * Default constructor
	 */
	public PuzzlePieceMatrixTransformer() {

	}

	/**
	 * Rotate and flip if necessary the matrix representation of the specified
	 * puzzle piece
	 * 
	 * @param puzzlePiece
	 *            a puzzle piece containing a matrix that needs to adjusted to
	 *            match the puzzle piece's state (flip, rotation)
	 */
	public void adjustPuzzlePieceMatrix(PuzzlePiece puzzlePiece) {
		// should flip?
		if (puzzlePiece.isFlipped()) {
			flipPuzzlePieceMatrix(puzzlePiece);
		}
		// should rotate?
		if (puzzlePiece.getRotationCount() > 0) {
			rotatePuzzlePieceMatrixClockwise(puzzlePiece);
		}
	}

	/**
	 * Inverts the matrix representation of a puzzle piece
	 * 
	 * @param puzzlePiece
	 *            a puzzle piece containing a matrix that needs to be flipped
	 */
	public void flipPuzzlePieceMatrix(PuzzlePiece puzzlePiece) {
		MatrixUtils.flipMatrixLeftToRightInPlace(puzzlePiece.getMatrix());
	}

	/**
	 * Rotates clockwise the matrix representation of a puzzle piece as many
	 * times as defined by its {@link PuzzlePieceRotation} property
	 * 
	 * @param puzzlePiece
	 *            a puzzle piece containing a matrix that needs to be rotated
	 *            clockwise
	 */
	private void rotatePuzzlePieceMatrixClockwise(PuzzlePiece puzzlePiece) {
		for (int rotationCount = 1; rotationCount <= puzzlePiece
				.getRotationCount(); rotationCount++) {
			rotatePuzzlePieceMatrixClockwiseOnce(puzzlePiece);
		}
	}

	/**
	 * Rotates once clockwise the matrix representation of a puzzle piece
	 * 
	 * @param puzzlePiece
	 *            a puzzle piece containing a matrix that needs to be rotated
	 *            once clockwise
	 */
	public void rotatePuzzlePieceMatrixClockwiseOnce(PuzzlePiece puzzlePiece) {
		MatrixUtils.rotateMatrixClockwiseInPlace(puzzlePiece.getMatrix());
	}

	/**
	 * Rotates once counter-clockwise the matrix representation of a puzzle
	 * piece
	 * 
	 * @param puzzlePiece
	 *            a puzzle piece containing a matrix that needs to be rotated
	 *            once counter-clockwise
	 */
	public void rotatePuzzlePieceMatrixCounterClockwiseOnce(
			PuzzlePiece puzzlePiece) {
		MatrixUtils
				.rotateMatrixCounterClockwiseInPlace(puzzlePiece.getMatrix());
	}
}
